package main

import (
	"fmt"
	"sync"
	"sync/atomic"
)

// 顺序打印 dog fish cat 100次
func main() {
	var wg sync.WaitGroup
	var dogCount int32
	var fishCount int32
	var catCount int32

	dogChan := make(chan struct{}, 1)
	fishChan := make(chan struct{}, 1)
	catChan := make(chan struct{}, 1)

	defer close(dogChan)
	defer close(fishChan)
	defer close(catChan)

	wg.Add(3)

	go dog(&wg, dogCount, dogChan, fishChan)
	go fish(&wg, fishCount, fishChan, catChan)
	go cat(&wg, catCount, catChan, dogChan)

	dogChan <- struct{}{}

	wg.Wait()
}

func dog(wg *sync.WaitGroup, count int32, dogChan, fishChan chan struct{}) {
	for true {
		if count >= 100 {
			wg.Done()
			return
		}
		<-dogChan
		fmt.Println("dog ", count)
		atomic.AddInt32(&count, 1)
		fishChan <- struct{}{}
	}
}

func fish(wg *sync.WaitGroup, count int32, fishChan, catChan chan struct{}) {
	for true {
		if count >= 100 {
			wg.Done()
			return
		}
		<-fishChan
		fmt.Println("fish ", count)
		atomic.AddInt32(&count, 1)
		catChan <- struct{}{}
	}
}

func cat(wg *sync.WaitGroup, count int32, catChan, dogChan chan struct{}) {
	for true {
		if count >= 100 {
			wg.Done()
			return
		}
		<-catChan
		fmt.Println("cat ", count)
		atomic.AddInt32(&count, 1)
		dogChan <- struct{}{}
	}
}
